#pragma once
#include <iostream>
#include <string>
#include "Socket.hpp"
#include "Log.hpp"
#include "Epoll.hpp"
#include <memory>
#include <unordered_map>
#include <functional>
#include <cerrno>
#include "setnoblock.hpp"

class Connection;
class Tcpserve;
uint32_t EVENT_IN = (EPOLLIN | EPOLLET);
uint32_t EVENT_OUT = (EPOLLOUT | EPOLLET);
const static int g_buffer_size = 128;

const uint16_t defaultport = 9998;
const int num = 128;
using func_t = std::function<void(weak_ptr<Connection>)>;

class Connection
{
public:
    Connection(int sockfd) : sockfd_(sockfd)
    {
    }
    int Fd()
    {
        return sockfd_;
    }
    void Sethandler(func_t recv, func_t send, func_t exept) // 设置回调函数
    {
        recv_cb = recv;
        send_cb = send;
        exept_cb = exept;
    }
    void SetWeakPtr(std::weak_ptr<Tcpserve> tcp_server_ptr)
    {
        tcp = tcp_server_ptr;
    }
    void Appendinbuffer(string &in)
    {
        inbuffer+=in;
    }
    void Appendoutbuffer(string& out)
    {
        outbuffer+=out;
    }
    string& Getinbuffer()
    {
        return inbuffer;
    }
    string& Getoutbuffer()
    {
        return outbuffer;
    }
    ~Connection()
    {
    }

private:
    int sockfd_;
    string inbuffer;
    string outbuffer;

public:
    func_t recv_cb;
    func_t send_cb;
    func_t exept_cb;
    /// Connection 对象需要访问 TcpServer 的功能，但又不能形成 shared_ptr 循环引用（会导致内存泄漏）
    // 使用 weak_ptr 可以安全地访问 TcpServer，同时不影响其生命周期管理
    weak_ptr<Tcpserve> tcp;
};

class Tcpserve :public std::enable_shared_from_this<Tcpserve>, public nocopy
{
public:
    Tcpserve(uint16_t port = defaultport,func_t callback=nullptr) 
    : port_(port)
    , callback_(callback)
    ,listensock_ptr(std::make_shared<Sock>())
    , epoll_ptr(std::make_shared<Epoll>())
    {
    }
    void Init() // 0
    {
        listensock_ptr->Socket();
        Setnoblock(listensock_ptr->Fd());
        listensock_ptr->Bind(port_);
        listensock_ptr->Listen();
        lg(Info, "create listensock succes:%d", listensock_ptr->Fd());
        Add(listensock_ptr->Fd(), EVENT_IN, std::bind(&Tcpserve::Accepter, this, std::placeholders::_1), nullptr, nullptr); // 3
    }
    void Add(int sock, uint32_t event, func_t recv, func_t send, func_t execpt)
    {
        shared_ptr<Connection> newconnection = std::make_shared<Connection>(sock); // connection管理sock连接信息
        newconnection->Sethandler(recv, send, execpt);
        epoll_ptr->EpollCtl(EPOLL_CTL_ADD, sock, event);          // 关心事件
        _connections.insert(std::make_pair(sock, newconnection)); // 哈希管理
        newconnection->SetWeakPtr(shared_from_this());
    }
    // 连接管理
    void Accepter(weak_ptr<Connection> conn)
    {
        auto connection = conn.lock(); // 将weak_ptr转换为shared_ptr
        while (true)
        {
            struct sockaddr_in client;
            socklen_t len = sizeof(client);
            int sockfd = accept(listensock_ptr->Fd(), (struct sockaddr *)&client, &len);
            cout << sockfd << endl;
            if (sockfd > 0)
            {
                uint16_t clientport = ntohs(client.sin_port);
                char ipbuf[128];
                inet_ntop(AF_INET, &client.sin_addr.s_addr, ipbuf, sizeof(ipbuf));
                lg(Debug, "get a new client, get info-> [%s:%d], sockfd : %d", ipbuf, clientport, sockfd);
                Setnoblock(sockfd);
                Add(sockfd, EVENT_IN,
                    std::bind(&Tcpserve::Recv, this, std::placeholders::_1),
                    std::bind(&Tcpserve::Send, this, std::placeholders::_1),
                    std::bind(&Tcpserve::Execpt, this, std::placeholders::_1));
            }
            // else
            // {
            //     if (errno == EWOULDBLOCK)
            //         break;
            //     else if (errno == EINTR)
            //         continue;
            //     else
            //         break;
            // }
            else
            {
                if (errno == EWOULDBLOCK)
                {
                    lg(Debug, "accept EWOULDBLOCK, no more connections");
                    break;
                }
                else if (errno == EINTR)
                {
                    lg(Debug, "accept EINTR, interrupted by signal, retry");
                    continue;
                }
                else
                {
                    lg(Error, "accept error: %s, return value: %d", strerror(errno), sockfd);
                    break;
                }
            }
        }
    }
    void Recv(weak_ptr<Connection> conn)
    {
        //expired()：快速判断 weak_ptr 所指对象是否存活，避免对无效对象的操作。
        if(conn.expired()) return;
        auto connection=conn.lock();
        int fd=connection->Fd();
        while(true)
        {
            char buffer[g_buffer_size];
            memset(buffer,0,sizeof(buffer));
            int n=recv(fd,buffer,sizeof(buffer),0);
            if(n>0)
            {
                string info=buffer;
                connection->Appendinbuffer(info);
                std::cout << "服务器收到原始数据: [" << info << "]" << std::endl;
                // cout<<connection->Getinbuffer()<<endl;
            }
            else if (n == 0)
            {
                lg(Info, "sockfd: %d, client info %s:%d quit...", fd/*, connection->_ip.c_str(), connection->_port*/);
                connection->exept_cb(connection);
                return;
            }
        else
        {
            // 错误处理
            if (errno == EWOULDBLOCK)
            {
                // ET 模式下，无更多数据可读，退出循环
                break;
            }
            else if (errno == EINTR)
            {
                // 被信号中断，重试
                continue;
            }
            else
            {
                // 其他错误（如连接重置）
                lg(Error, "Recv error on fd %d: %s", fd, strerror(errno));
                epoll_ptr->EpollCtl(EPOLL_CTL_DEL, fd, 0);
                _connections.erase(fd);
                break;
            }
        }     
        }
    callback_(connection);
    }
    void Send(weak_ptr<Connection> conn)
    {
        if(conn.expired()) return;
        auto connection=conn.lock();//转化强指针，确保后续操作有效
        string &outbuffer=connection->Getoutbuffer();/////一定加引用，否则outbuffer的缓冲区数据库没清除
        while(true)
        {
        int n=send(connection->Fd(),outbuffer.c_str(),outbuffer.size(),0);

        if(n > 0)
        {
            // 发送成功，从缓冲区中移除已发送的数据
            outbuffer.erase(0, n);
            if(outbuffer.empty()) break;  // 缓冲区为空，退出循环
        }
        else if(n == 0)
        {
            return;
        }
        else
        {
            // 处理错误
            if(errno == EWOULDBLOCK) break;  // 暂时无法发送，退出循环
            else if(errno == EINTR) continue; // 被信号中断，重试
            else
            {
                lg(Warning, "sockfd: %d, client info  send error...", connection->Fd()/*, connection->_ip.c_str(), connection->_port*/);
                connection->exept_cb(connection);//
                return;
            }
        }
        }
    
    //根据缓冲区状态调整epoll事件关注
    if(!outbuffer.empty())
    {
        // 缓冲区还有数据，继续关注写事件
        EnableEvent(connection->Fd(), true, true);
    }
    else
    {
        // 缓冲区为空，停止关注写事件
        EnableEvent(connection->Fd(), true, false);
    }
    }
    // void Send(std::weak_ptr<Connection> conn)
    // {
    //     if(conn.expired()) return;
    //     auto connection = conn.lock();
    //     auto &outbuffer = connection->Getoutbuffer();
    //     while(true)
    //     {
    //         ssize_t n = send(connection->Fd(), outbuffer.c_str(), outbuffer.size(), 0);
    //         if(n > 0)
    //         {
    //             outbuffer.erase(0, n);
    //             if(outbuffer.empty()) break;
    //         }
    //         else if(n == 0)
    //         {
    //             return;
    //         }
    //         else
    //         {
    //             if(errno == EWOULDBLOCK) break;
    //             else if(errno == EINTR) continue;
    //             else{
    //                 lg(Warning, "sockfd: %d, client info send error...", connection->Fd());
    //                 connection->exept_cb(connection);
    //                 return;
    //             }
    //         }
    //     }
    //     if(!outbuffer.empty())
    //     {
    //         // 开启对写事件的关心
    //         EnableEvent(connection->Fd(), true, true);
    //     }
    //     else
    //     {
    //         // 关闭对写事件的关心
    //         EnableEvent(connection->Fd(), true, false);
    //     }
    // }
    void Execpt(weak_ptr<Connection> connection)
    {
        if(connection.expired()) return;
        auto conn = connection.lock();

        int fd = conn->Fd();
        lg(Warning, "Excepter hander sockfd: %d, client info  excepter handler",
           conn->Fd()/*, conn->_ip.c_str(), conn->_port*/);
        // 1. 移除对特定fd的关心
        // EnableEvent(connection->SockFd(), false, false);
        epoll_ptr->EpollCtl(EPOLL_CTL_DEL, fd, 0);
        // 2. 关闭异常的文件描述符
        lg(Debug, "close %d done...\n", fd);
        close(fd);
        // 3. 从unordered_map中移除
        lg(Debug, "remove %d from _connections...\n", fd);
        // TODO bug
        // auto iter = _connections.find(fd);
        // if(iter == _connections.end()) return;
        // _connections.erase(iter);
        // _connections[fd].reset();
        _connections.erase(fd);
    }
    void EnableEvent(int sock, bool readable, bool writeable)
    {
        uint32_t events = 0;
        events |= ((readable ? EPOLLIN : 0) | (writeable ? EPOLLOUT : 0) | EPOLLET);
        epoll_ptr->EpollCtl(EPOLL_CTL_MOD, sock, events);
    }
    bool IsEffective(int fd) // 判断是否有效
    {
        auto it = _connections.find(fd);
        if (it == _connections.end())
            return false;
        return true;
    }
    void Distribute(int timeout) // 2,派发
    {
        int n = epoll_ptr->EpollWait(revents, num, timeout);
        for (int i = 0; i < n; i++)
        {
            int sockfd = revents[i].data.fd;
            uint32_t event = revents[i].events;
            if (event & EPOLLIN && IsEffective(sockfd))
            {
                if (_connections[sockfd]->recv_cb)
                    _connections[sockfd]->recv_cb(_connections[sockfd]);
            }
            if (event & EPOLLOUT && IsEffective(sockfd))
            {
                if (_connections[sockfd]->send_cb)
                    _connections[sockfd]->send_cb(_connections[sockfd]);
            }
        }
    }
    void start() // 1
    {
        cmz = true;
        while (cmz)
        {
            Distribute(-1);
            PrintConnection();
        }
        cmz=false;
    }
    void PrintConnection()
    {
        std::cout << "_connections fd list: ";
        for (auto &connection : _connections)
        {
            std::cout << connection.second->Fd() << ", ";
            // std::cout << "inbuffer: " << _connections.second->inbuffer().c_str();
        }
        std::cout << std::endl;
    }
    ~Tcpserve()
    {
    }

private:
    shared_ptr<Sock> listensock_ptr; // 记得初始化
    uint16_t port_;
    struct epoll_event revents[num];
    shared_ptr<Epoll> epoll_ptr;                             // 管理事件
    unordered_map<int, shared_ptr<Connection>> _connections; // 把文件描述符和连接绑在一起
    bool cmz = false;                                   // 服务器启动
    func_t callback_;
};
